package io.gitee.hchaojie.day09;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Factory {
    private static final int MAX = 5;

    List<Integer> products = new ArrayList<>();

    private Lock lock = new ReentrantLock();        // 重入锁

    private Condition notEmpty = lock.newCondition();       // 创建一个工厂非空的条件
    private Condition notFull = lock.newCondition();        // 创建一个工厂不满的条件

    // 生产者往工厂放数据
    public void put(Integer i) {
        lock.lock();        // 从这个地方开始，锁定一段代码块，一次只能一个线程进来执行

        try {
            if (products.size() >= 5) {
                try {
                    System.out.println("工厂容量达到上限。。。");

                    // 等待工厂不满这个条件的成立
                    notFull.await();

                    // wait();         // 等待消费者取数据，等待products不满这个条件
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            products.add(i);

            // notify();       // 通知消费者，工厂里面有数据了，可以继续取
            notEmpty.signal();

            System.out.println("生产者放入了一个产品：" + i);
        } finally {
            lock.unlock();      // 解锁
        }
    }

    public Integer get() {
        lock.lock();
        try {
            if (products.isEmpty()) {
                try {
                    System.out.println("工厂里面没有数据，需要等待。。。");

                    // 等待工厂不为空这个条件的成立
                    notEmpty.await();

                    // wait();         // 让当前线程处于等待状态，等待另一个线程唤醒它
                                    // wait会释放锁，wait必须在同步方法或者同步代码块里面
                                    // sleep不会释放锁
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            // 被其它线程唤醒

            Integer i = products.remove(0);
            System.out.println("#### 消费者取出了一个产品：" + i);
            // notify();       // 通知生产者，继续放数据
            notFull.signal();   // 发出信号：不满这个条件成立了

            return i;
        } finally {
            lock.unlock();
        }
    }
}
